home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / qlib205.zip / QLIB.ZIP / SRC / QLIB / SPRINT.ASM < prev    next >
Assembly Source File  |  1997-01-20  |  9KB  |  473 lines

  1. include qlib.inc  ;setup
  2. include dos.inc
  3. include string.inc
  4. include conio.inc
  5. include stdlib.inc
  6.  
  7. .data?
  8. align 4
  9.   _bak dd ?
  10.   _width dd ?
  11.   _pad dd ?   ;used with %s when width is used
  12.   _dec dd ?   ;width after . (%f)
  13.  
  14.   tempstr db 64 dup(?)
  15.  
  16.   _pos db ?   ;flag : use positive sign on signed #'s
  17.   _zero db ?  ;flag : do not remove leading zeros
  18.   _dot db ?   ;flag : . used with %f
  19.   _decu db ?  ;flag : is _dec used?
  20.   _typ db ?   ;type : the char after the % (ie: d,x,X,c,s,f,etc.)
  21.  
  22.   epos dd ?  ;used for %f and %e
  23.   esiz dd ? 
  24.  
  25. .code
  26. decode_per proc private uses ecx
  27.   ; in : esi=string (right after %)
  28.   ;    : ebx=varargs
  29.   ; out : eax=# bytes needed
  30.   ;     : _typ=char (c,s,d...)
  31.   ;     : _width=byte (max=9999)
  32.   ;     : _zero = T/F
  33.   ;     : _pos = T/F
  34.  
  35.   local m:byte
  36.  
  37.   mov m,0
  38.   mov _pos,0
  39.   mov _zero,0
  40.   mov _width,0
  41.   mov _dot,0
  42.   mov _dec,0      ;decimal width for decimals (BC uses 6 which is dumb)
  43.   mov _decu,0
  44.   mov _bak,esi
  45. @@:
  46.   lodsb
  47. gotit:
  48.   .if al=='.'
  49.     .if _dot
  50.       jmp bad
  51.     .endif
  52.     inc _dot
  53.     mov m,0
  54.     jmp @b
  55.   .endif
  56.   .if (al=='0') && (!_zero) && (!_width) && (!_dot)
  57.     inc _zero
  58.     jmp @b
  59.   .endif
  60.   .if (al=='+')
  61.     .if _pos
  62.       jmp bad
  63.     .endif
  64.     inc _pos
  65.     jmp @b
  66.   .endif
  67.   .if (al>='0') && (al<='9')
  68.     .if _dot
  69.       mov _decu,1
  70.       .if m > 5
  71.         jmp @b    ;ignore # (it's large enough)
  72.       .endif
  73.       mov ecx,_dec
  74.       imul ecx,10
  75.       inc m
  76.       sub al,'0'
  77.       xor ah,ah
  78.       add cx,ax
  79.       mov _dec,ecx
  80.       jmp @b
  81.     .endif
  82.     .if m > 5
  83.       jmp @b      ;ignore # (it's large enough)
  84.     .endif
  85.     mov ecx,_width
  86.     imul ecx,10
  87.     inc m
  88.     sub al,'0'
  89.     xor ah,ah
  90.     add cx,ax
  91.     mov _width,ecx
  92.     jmp @b
  93.   .endif
  94.  
  95.   .if al=='f'
  96.     mov _typ,al
  97.     mov eax,64
  98.     add ebx,4   ;add an aditional 4bytes cause floats are 64bit (double!)
  99.     jmp done
  100.   .endif
  101.   .if al=='e'
  102.     mov _typ,al
  103.     mov eax,64
  104.     add ebx,4   ;add an aditional 4bytes cause floats are 64bit (double!)
  105.     jmp done
  106.   .endif
  107.   .if (_dot)
  108.     jmp bad
  109.   .endif
  110.  
  111.   .if al=='b'
  112.     mov _typ,al  ;binary
  113.     mov eax,33
  114.     jmp done
  115.   .endif
  116.   .if al=='o'
  117.     mov _typ,al ;octal
  118.     mov eax,17
  119.     jmp done
  120.   .endif
  121.   .if al=='x'
  122.     mov _typ,al ;hex
  123.     mov eax,9
  124.     jmp done
  125.   .endif
  126.   .if al=='X'
  127.     mov _typ,al ;HEX
  128.     mov eax,9
  129.     jmp done
  130.   .endif
  131.   .if al=='u'
  132.     mov _typ,al   ;unsigned
  133.     mov eax,11
  134.     jmp done
  135.   .endif
  136.   .if al=='d' || al=='i'    ;signed
  137.     mov _typ,al
  138.     mov eax,12
  139.     jmp done
  140.   .endif
  141.   
  142.   .if (_zero) || (_pos) || (_dot)
  143.     jmp bad
  144.   .endif
  145.  
  146.   .if al=='s'   ;string
  147.     mov _typ,al
  148.     mov eax,[ebx]
  149.     callp strlen,eax
  150.     .if eax < _width
  151.       mov ecx,_width
  152.       mov _pad,ecx
  153.       sub _pad,eax
  154.       mov eax,ecx
  155.     .endif
  156.     jmp done
  157.   .elseif al=='c'
  158.     mov _typ,al
  159.     mov eax,1
  160.     jmp done
  161.   .endif
  162.   jmp bad
  163.  
  164. done:
  165.   .if _width > eax   ;make sure to return largest #
  166.     mov eax,_width
  167.   .endif
  168.   add ebx,4
  169.   ret
  170. bad:
  171.   mov esi,_bak
  172.   mov _typ,0
  173.   xor eax,eax
  174.   ret
  175. decode_per endp
  176.  
  177. _printf_siz proc,str1:dword,args:vararg
  178.   ;calculate maximum RAM required for string when all % expanded.
  179.   ; out : eax = max size needed
  180.   lea eax,args
  181.   callp _vprintf_siz,str1,eax
  182.   ret
  183. _printf_siz endp
  184.  
  185. _vprintf_siz proc,str1:dword,args:dword
  186.   local siz:dword
  187.   pushad
  188.   mov esi,str1
  189.   mov ebx,args
  190.   mov siz,0
  191. @@:
  192.   cmp byte ptr[esi],0
  193.   jz @f
  194.   cmp byte ptr[esi],'%'
  195.   jz @@per
  196.   inc siz
  197.   inc esi
  198.   jmp @b
  199. @@per:
  200.   inc esi
  201.   cmp byte ptr[esi],'%'
  202.   jnz @@per2
  203.   inc esi
  204.   inc siz  ;just one % will go out
  205.   jmp @b
  206. @@per2:
  207.   call decode_per
  208.   .if !eax
  209.     inc siz ;for the % (w/ error)
  210.   .elseif
  211.     add siz,eax
  212.   .endif
  213.   jmp @b
  214. @@:
  215.   inc siz ;for the 0
  216.   popad
  217.   mov eax,siz
  218.   ret
  219. _vprintf_siz endp                                    
  220.  
  221. ;prints into string
  222. sprintf proc,buf:dword,str1:dword,args:vararg
  223.   lea eax,args
  224.   callp vsprintf,buf,str1,eax
  225.   ret
  226. sprintf endp
  227.  
  228. vsprintf proc,buf:dword,str1:dword,args:dword
  229.   ;prints C type string from src => dest
  230.  
  231.   ; % [+][0][width][S] type
  232.   ; type=[d],[o],[x],[X],[b],[c],[s],[%],[f]
  233.  
  234.   ; +=use + when printing signed #'s
  235.   ; 0=keep all leading zeros 
  236.   ; S=signed modifier (error if used with 'c' or 's')
  237.   ; x,X=hex output (as in C)
  238.   ; b=binary output
  239.   ; d=decimal output
  240.   ; c=char
  241.   ; s=string
  242.   ; f=double (DO NOT USE FLOAT)
  243.   
  244.   ; NO LOCALS ALLOWED
  245.  
  246.   ; FIX : v2.00 Beta #2 : this was not preserving regs!
  247.  
  248.   pushad
  249.  
  250.   mov esi,str1
  251.   mov edi,buf
  252.   mov ebx,args
  253.  
  254.   mov ebp,ebx
  255. @@top:
  256.   mov al,[esi]
  257.   cmp al,0
  258.   jz __end
  259.   cmp al,'%'
  260.   jz @@per
  261. @@per1:  
  262.   movsb
  263.   jmp @@top
  264. @@per: ; % is use
  265.   inc esi
  266.   mov al,[esi]
  267.   cmp al,'%'
  268.   jz @@per1    ;2 % = 1 %
  269.   mov ebx,ebp
  270.   call decode_per
  271.   mov al,_typ
  272.   cmp al,0
  273.   jz __end
  274.  
  275.   cmp al,'u'
  276.   jz @@peru
  277.   cmp al,'i'
  278.   jz @@perd
  279.   cmp al,'d'
  280.   jz @@perd
  281.   cmp al,'x'
  282.   jz @@perx
  283.   cmp al,'X'
  284.   jz @@perxc
  285.   cmp al,'c'
  286.   jz @@perc
  287.   cmp al,'o'
  288.   jz @@pero
  289.   cmp al,'b'
  290.   jz @@perb
  291.   cmp al,'e'
  292.   jz @@perf
  293.   cmp al,'f'
  294.   jz @@perf
  295. ;must be 's'
  296.   .if _width && _pad
  297.     mov al,32
  298.     mov ecx,_pad
  299.     rep stosb
  300.   .endif
  301.   callp strcpy,edi,[ebp]
  302.   callp strlen,[ebp]
  303.   add edi,eax
  304.   add ebp,4
  305.   jmp @@top
  306. @@perf:
  307.   .if _dec > 40
  308.     mov _dec,40  ;no more than this is needed
  309.   .endif
  310.   .if !_decu
  311.     mov _dec,6
  312.   .endif
  313.   .if al=='f'
  314.     callp ftoa,REAL8 PTR[ebp],offset tempstr,_dec
  315.   .else  ;'e'
  316.     callp etoa,REAL8 PTR[ebp],offset tempstr,_dec
  317.   .endif
  318.   jmp addfstr
  319. @@perb:
  320.   callp num2str,[ebp],offset tempstr,2
  321.   jmp addstr
  322. @@pero:
  323.   callp num2str,[ebp],offset tempstr,8
  324.   jmp addstr
  325. @@perd:
  326.   callp num2strs,[ebp],offset tempstr,10     ;signed!
  327.   jmp addstr
  328. @@peru:
  329.   callp num2str,[ebp],offset tempstr,10      ;unsigned!
  330.   jmp addstr
  331. @@perx:    ;hex w/ lower case
  332.   callp num2str,[ebp],offset tempstr,16
  333.   jmp addstr
  334. @@perxc:   ;hex w/capitals
  335.   callp num2strc,[ebp],offset tempstr,16
  336.   jmp addstr
  337. @@perc:
  338.   mov al,[ebp]
  339.   mov [edi],al
  340.   inc edi
  341.   add ebp,4    ;no byte pushes possible
  342.   jmp @@top
  343. __end:
  344.   mov byte ptr[edi],0
  345.   popad
  346.   xor eax,eax
  347.   ret
  348. addstr:
  349.   add ebp,4      ;move to next var.
  350.   ;copy tempstr to edi based on _*
  351.   push esi
  352.   mov esi,offset tempstr
  353.   .if (_pos) && (bptr[esi]!='-')
  354.     mov eax,esi
  355.     inc eax
  356.     callp memcpy,eax,esi,sizeof tempstr - 1
  357.     mov bptr[esi],'+'
  358.   .endif
  359.   callp strlen,esi
  360.   mov ebx,eax
  361.   .if eax < _width
  362.     mov ecx,_width
  363.     sub ecx,eax
  364.     mov al,[esi]
  365.     .if ( ( (al=='-') || (al=='+') ) && _zero )
  366.       movsb
  367.       dec ebx
  368.     .endif
  369.     .if _zero
  370.       mov al,'0'
  371.     .else
  372.       mov al,32
  373.     .endif
  374.     rep stosb
  375.   .endif
  376.   mov ecx,ebx
  377.   rep movsb
  378.   pop esi
  379.   jmp @@top
  380. addfstr:  ;special for %f
  381.   add ebp,8      ;move to next var.
  382.   ;copy tempstr to edi based on _*
  383.   push esi
  384.   mov esi,offset tempstr
  385.   .if bptr[esi+1]=='N' || bptr[esi+1]=='I'   ;was it NAN or INF?
  386.     mov edx,4
  387.     mov _zero,0
  388.     mov epos,0
  389.     mov esiz,0
  390.     jmp specialperf
  391.   .endif
  392.   .if (_pos) && (bptr[esi]!='-')
  393.     mov eax,esi
  394.     inc eax
  395.     callp memcpy,eax,esi,sizeof tempstr - 1
  396.     mov bptr[esi],'+'
  397.   .endif
  398.   call flen  ;EBX= whole length  ECX=pos of e EDX=size of e
  399.   mov epos,ecx
  400.   mov esiz,edx
  401.   add edx,ebx
  402.   add edx,_dec  ;6+1 for dec pt
  403.   .if _dec      ;if _dec is zero then the decimal should not be printed
  404.     inc edx     ;include the dec pt
  405.   .endif
  406. specialperf:
  407.   .if edx < _width
  408.     mov ecx,_width
  409.     sub ecx,edx
  410.     mov al,[esi]
  411.     .if ( ( (al=='-') || (al=='+') ) && _zero )
  412.       movsb
  413.       dec edx  ;just outputed 1 byte now so do not do it l8r
  414.     .endif
  415.     .if _zero
  416.       mov al,'0'
  417.     .else
  418.       mov al,' '
  419.     .endif
  420.     rep stosb
  421.   .endif
  422.   mov ecx,edx
  423.   sub ecx,esiz
  424.   rep movsb  ;move # first
  425.   .if epos   ;is there an exp part
  426.     mov esi,epos  ;move to exp part
  427.     mov ecx,esiz
  428.     rep movsb
  429.   .endif
  430.   pop esi
  431.   jmp @@top
  432. vsprintf endp
  433.  
  434. ;ret: EBX=whole len ECX=pos of e if exp # (ie: 1e3) else 0 EDX=size of exp part
  435. ;in : esi = string
  436. flen proc private uses esi
  437.   xor ebx,ebx
  438.   xor ecx,ecx
  439.   xor edx,edx
  440.   lodsb
  441.   .while al!='.' && al!='e' && al!=0
  442.     inc ebx
  443.     lodsb
  444.   .endw
  445.   .if al==0
  446.     ret
  447.   .endif
  448.   .if al=='e'
  449.     jmp e1
  450.   .endif
  451.   lodsb
  452.   .while al!='e' && al!=0
  453.     lodsb
  454.   .endw
  455.   .if al==0
  456.     ret
  457.   .endif
  458. ;exp form detected
  459. e1:
  460.   mov ecx,esi
  461.   dec ecx
  462.   inc edx        ;inc for the 'e'
  463.   lodsb
  464.   .while al!=0
  465.     inc edx
  466.     lodsb
  467.   .endw
  468.   ret
  469. flen endp
  470.  
  471. end
  472.  
  473.